home *** CD-ROM | disk | FTP | other *** search
/ Programming Windows (5th Edition) / Programming Windows, 5th ed. - Companion CD (097-0002183)(1999).iso / Chap16 / ShowDib3 / PackeDib.c next >
Encoding:
C/C++ Source or Header  |  1998-10-09  |  7.4 KB  |  227 lines

  1. /*----------------------------------------------
  2.    PACKEDIB.C -- Routines for using packed DIBs
  3.                  (c) Charles Petzold, 1998
  4.   ----------------------------------------------*/
  5.  
  6. #include <windows.h>
  7.  
  8. /*---------------------------------------------------------
  9.    PackedDibLoad: Load DIB File as Packed-Dib Memory Block
  10.   ---------------------------------------------------------*/
  11.  
  12. BITMAPINFO * PackedDibLoad (PTSTR szFileName)
  13. {
  14.      BITMAPFILEHEADER bmfh ;
  15.      BITMAPINFO     * pbmi ;
  16.      BOOL             bSuccess ;
  17.      DWORD            dwPackedDibSize, dwBytesRead ;
  18.      HANDLE           hFile ;
  19.  
  20.           // Open the file: read access, prohibit write access
  21.  
  22.      hFile = CreateFile (szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, 
  23.                          OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL) ;
  24.  
  25.      if (hFile == INVALID_HANDLE_VALUE)
  26.           return NULL ;
  27.  
  28.           // Read in the BITMAPFILEHEADER
  29.  
  30.      bSuccess = ReadFile (hFile, &bmfh, sizeof (BITMAPFILEHEADER), 
  31.                           &dwBytesRead, NULL) ;
  32.  
  33.      if (!bSuccess || (dwBytesRead != sizeof (BITMAPFILEHEADER))         
  34.                    || (bmfh.bfType != * (WORD *) "BM"))
  35.      {
  36.           CloseHandle (hFile) ;
  37.           return NULL ;
  38.      }
  39.  
  40.           // Allocate memory for the packed-DIB & read it in
  41.  
  42.      dwPackedDibSize = bmfh.bfSize - sizeof (BITMAPFILEHEADER) ;
  43.  
  44.      pbmi = malloc (dwPackedDibSize) ;
  45.  
  46.      bSuccess = ReadFile (hFile, pbmi, dwPackedDibSize, &dwBytesRead, NULL) ;
  47.      CloseHandle (hFile) ;
  48.  
  49.      if (!bSuccess || (dwBytesRead != dwPackedDibSize))
  50.      {
  51.           free (pbmi) ;
  52.           return NULL ;
  53.      }
  54.  
  55.      return pbmi ;
  56. }
  57.  
  58. /*----------------------------------------------
  59.    Functions to get information from Packed Dib
  60.   ----------------------------------------------*/
  61.  
  62. int PackedDibGetWidth (BITMAPINFO * pPackedDib)
  63. {
  64.      if (pPackedDib->bmiHeader.biSize == sizeof (BITMAPCOREHEADER))
  65.           return ((PBITMAPCOREINFO)pPackedDib)->bmciHeader.bcWidth ;
  66.      else
  67.           return pPackedDib->bmiHeader.biWidth ;
  68. }
  69.  
  70. int PackedDibGetHeight (BITMAPINFO * pPackedDib)
  71. {
  72.      if (pPackedDib->bmiHeader.biSize == sizeof (BITMAPCOREHEADER))
  73.           return ((PBITMAPCOREINFO)pPackedDib)->bmciHeader.bcHeight ;
  74.      else
  75.           return abs (pPackedDib->bmiHeader.biHeight) ;
  76. }
  77.  
  78. int PackedDibGetBitCount (BITMAPINFO * pPackedDib)
  79. {
  80.      if (pPackedDib->bmiHeader.biSize == sizeof (BITMAPCOREHEADER))
  81.           return ((PBITMAPCOREINFO)pPackedDib)->bmciHeader.bcBitCount ;
  82.      else
  83.           return pPackedDib->bmiHeader.biBitCount ;
  84. }
  85.  
  86. int PackedDibGetRowLength (BITMAPINFO * pPackedDib)
  87. {
  88.      return ((PackedDibGetWidth (pPackedDib) * 
  89.               PackedDibGetBitCount (pPackedDib) + 31) & ~31) >> 3 ;
  90. }
  91.  
  92. /*-----------------------------------------------------------
  93.    PackedDibGetInfoHeaderSize includes possible color masks!
  94.   -----------------------------------------------------------*/
  95.  
  96. int PackedDibGetInfoHeaderSize (BITMAPINFO * pPackedDib)
  97. {
  98.      if (pPackedDib->bmiHeader.biSize == sizeof (BITMAPCOREHEADER))
  99.           return ((PBITMAPCOREINFO)pPackedDib)->bmciHeader.bcSize ;
  100.  
  101.      else if (pPackedDib->bmiHeader.biSize == sizeof (BITMAPINFOHEADER))
  102.           return pPackedDib->bmiHeader.biSize + 
  103.                     (pPackedDib->bmiHeader.biCompression == 
  104.                                         BI_BITFIELDS ? 12 : 0) ;
  105.  
  106.      else return pPackedDib->bmiHeader.biSize ;
  107. }
  108.  
  109. /*-------------------------------------------------------------
  110.    PackedDibGetColorsUsed returns value in information header;
  111.           could be 0 to indicate non-truncated color table!
  112.   -------------------------------------------------------------*/
  113.  
  114. int PackedDibGetColorsUsed (BITMAPINFO * pPackedDib)
  115. {
  116.      if (pPackedDib->bmiHeader.biSize == sizeof (BITMAPCOREHEADER))
  117.           return 0 ;
  118.      else
  119.           return pPackedDib->bmiHeader.biClrUsed ;
  120. }
  121.  
  122. /*------------------------------------------------------------------
  123.    PackedDibGetNumColors is actual number of entries in color table
  124.   ------------------------------------------------------------------*/
  125.  
  126. int PackedDibGetNumColors (BITMAPINFO * pPackedDib)
  127. {
  128.      int iNumColors ;
  129.  
  130.      iNumColors = PackedDibGetColorsUsed (pPackedDib) ;
  131.  
  132.      if (iNumColors == 0 && PackedDibGetBitCount (pPackedDib) < 16)
  133.           iNumColors = 1 << PackedDibGetBitCount (pPackedDib) ;
  134.  
  135.      return iNumColors ;
  136. }
  137.  
  138. int PackedDibGetColorTableSize (BITMAPINFO * pPackedDib)
  139. {
  140.      if (pPackedDib->bmiHeader.biSize == sizeof (BITMAPCOREHEADER))
  141.           return PackedDibGetNumColors (pPackedDib) * sizeof (RGBTRIPLE) ;
  142.      else
  143.           return PackedDibGetNumColors (pPackedDib) * sizeof (RGBQUAD) ;
  144. }
  145.  
  146. RGBQUAD * PackedDibGetColorTablePtr (BITMAPINFO * pPackedDib)
  147. {
  148.      if (PackedDibGetNumColors (pPackedDib) == 0)
  149.           return 0 ;
  150.  
  151.      return (RGBQUAD *) (((BYTE *) pPackedDib) + 
  152.                                    PackedDibGetInfoHeaderSize (pPackedDib)) ;
  153. }
  154.  
  155. RGBQUAD * PackedDibGetColorTableEntry (BITMAPINFO * pPackedDib, int i)
  156. {
  157.      if (PackedDibGetNumColors (pPackedDib) == 0)
  158.           return 0 ;
  159.  
  160.      if (pPackedDib->bmiHeader.biSize == sizeof (BITMAPCOREHEADER))
  161.           return (RGBQUAD *) 
  162.                (((RGBTRIPLE *) PackedDibGetColorTablePtr (pPackedDib)) + i) ;
  163.      else
  164.           return PackedDibGetColorTablePtr (pPackedDib) + i ;
  165. }
  166.  
  167. /*------------------------------
  168.    PackedDibGetBitsPtr finally!
  169.   ------------------------------*/
  170.  
  171. BYTE * PackedDibGetBitsPtr (BITMAPINFO * pPackedDib)
  172. {
  173.      return ((BYTE *) pPackedDib) + PackedDibGetInfoHeaderSize (pPackedDib) +
  174.                                     PackedDibGetColorTableSize (pPackedDib) ;
  175. }
  176.  
  177. /*----------------------------------------------------------------------- 
  178.    PackedDibGetBitsSize can be calculated from the height and row length
  179.           if it's not explicitly in the biSizeImage field
  180.   -----------------------------------------------------------------------*/
  181.  
  182. int PackedDibGetBitsSize (BITMAPINFO * pPackedDib)
  183. {
  184.      if ((pPackedDib->bmiHeader.biSize != sizeof (BITMAPCOREHEADER)) &&
  185.          (pPackedDib->bmiHeader.biSizeImage != 0))
  186.          return pPackedDib->bmiHeader.biSizeImage ;
  187.  
  188.      return PackedDibGetHeight (pPackedDib) * 
  189.             PackedDibGetRowLength (pPackedDib) ;
  190. }
  191.  
  192. /*----------------------------------------------------------------
  193.    PackedDibCreatePalette creates logical palette from Packed DIB
  194.   ----------------------------------------------------------------*/
  195.  
  196. HPALETTE PackedDibCreatePalette (BITMAPINFO * pPackedDib)
  197. {
  198.      HPALETTE     hPalette ;
  199.      int          i, iNumColors ;
  200.      LOGPALETTE * plp ;
  201.      RGBQUAD    * prgb ;
  202.  
  203.      if (0 == (iNumColors = PackedDibGetNumColors (pPackedDib)))
  204.           return NULL ;
  205.  
  206.      plp = malloc (sizeof (LOGPALETTE) * 
  207.                          (iNumColors - 1) * sizeof (PALETTEENTRY)) ;
  208.  
  209.      plp->palVersion    = 0x0300 ;
  210.      plp->palNumEntries = iNumColors ;
  211.  
  212.      for (i = 0 ; i < iNumColors ; i++)
  213.      {
  214.           prgb = PackedDibGetColorTableEntry (pPackedDib, i) ;
  215.  
  216.           plp->palPalEntry[i].peRed   = prgb->rgbRed ;
  217.           plp->palPalEntry[i].peGreen = prgb->rgbGreen ;
  218.           plp->palPalEntry[i].peBlue  = prgb->rgbBlue ;
  219.           plp->palPalEntry[i].peFlags = 0 ;
  220.      }
  221.  
  222.      hPalette = CreatePalette (plp) ;
  223.      free (plp) ;
  224.  
  225.      return hPalette ;
  226. }
  227.